Skip to content

Paint solid token-meter cells as background, not as a block glyph - #1183

Merged
edwin-zvs merged 3 commits into
mainfrom
fix/token-meter-cell-seams
Aug 3, 2026
Merged

Paint solid token-meter cells as background, not as a block glyph#1183
edwin-zvs merged 3 commits into
mainfrom
fix/token-meter-cell-seams

Conversation

@edwin-zvs

Copy link
Copy Markdown
Contributor

The bug

In the operator panel's token meter, every bar reads as a stack of bricks with mortar lines between them — a hairline of panel background at every row boundary of every column.

before

Measured on two screenshots of the same panel in different themes:

cell pitch painted unpainted
tan theme 26 px 20 px 6 px at the top of every cell
blue theme 26 px 21 px 5 px at the top of every cell

Same offset in every cell, in every column, at every row boundary. That regularity is the tell: it isn't the data, it's the glyph.

Cause

A cell one band fills outright was drawn as a (FULL BLOCK) foreground glyph. A foreground glyph only colors the pixels the font draws, and plenty of fonts draw FULL BLOCK shorter than the terminal's line box — the leading is left transparent, so it shows panel background.

The right-hand screenshot above contains the proof of the fix: the one cell with no seam below it is a cell where a band boundary lands mid-cell, which the renderer already paints with a background color. A background fills the whole cell rect whatever the font does.

Fix

Spend the background on the band for cells it fills outright — nothing else can be painted into such a cell, so it costs nothing. Partially-filled cells keep their eighth-block glyph, because their empty part has to stay panel background; the short-glyph leading falls at the top of a column, against background that is empty anyway.

Notes for the reviewer

  • No vhs before/after. The artifact is font-dependent, and vhs's font draws FULL BLOCK filling the whole line box — I measured 5 stacked rows rendering as one solid 80 px run with no seams. A vhs pair would be two identical videos. The screenshots above are from the reporting terminal, where the artifact is real; an "after" from that same terminal is the meaningful confirmation.
  • Tradeoffs: with terminal background transparency the bars become opaque rather than tinted (arguably better), and copying the panel as text now yields spaces instead of .
  • token_meter_draws_bars_and_names_each_series had to move from scanning rendered text to inspecting cell paint within the graph area — a background-painted bar leaves no mark on the text layer.
  • The docs-media/ image is temporary and is removed in the next commit; the raw link above is pinned to the commit that carried it.

Testing

cargo test — full workspace, 52 test binaries, all green.

A bar cell one band fills outright was drawn as a `█` foreground glyph. A
foreground glyph only colors the pixels the font draws, and plenty of fonts
draw FULL BLOCK shorter than the terminal's line box — the leading is left
transparent, so every row boundary showed a hairline of panel background and
a solid bar read as a stack of bricks with mortar lines.

Measured on two screenshots of the operator panel: a 26px cell pitch with
only 20-21px painted, the same ~5-6px unpainted strip at the top of every
cell of every column. Cells where a band boundary lands mid-cell were
already immune, because they carry a background color and a background
fills the whole cell rect whatever the font does.

So spend the background on the band for cells it fills outright. Nothing
else can be painted into such a cell, so it costs nothing. Partially-filled
cells keep their eighth-block glyph — their empty part has to stay panel
background — and the short-glyph leading falls at the top of a column
against background that is empty anyway.
@edwin-zvs
edwin-zvs merged commit 8edba01 into main Aug 3, 2026
1 check passed
@edwin-zvs
edwin-zvs deleted the fix/token-meter-cell-seams branch August 3, 2026 04:01
edwin-zvs added a commit that referenced this pull request Aug 4, 2026
The fleet meter fixed hairline row seams by painting full cells as
background (#1183). The project dashboard kept a simplified path that
still used FULL BLOCK glyphs, so the same brick seams showed there.

Move column paint helpers into token_meter and use them for both
meters so solid bars stay solid on every font.
edwin-zvs added a commit that referenced this pull request Aug 5, 2026
Two fixes to the hover detail.

The cached figure was marked with `↺`, which reads as "refresh" and has
to be learned before the row can be read. It now says the word: `18k ·
9.0k cached`. The box was already sized from its rows, so it just gets
wider.

The bars ended on a partial block glyph, inherited from the column paint.
That cost a square edge: cells a band fills outright are painted as
background, and a foreground block beside them is only drawn where the
font puts ink — a font that draws it short of the line box (#1183)
notches the bar's corner, which reads as damage rather than precision.
Bars now spend whole cells only, every one a background fill, so the
rectangle is clean on any font. Largest-remainder apportionment keeps the
cached and fresh parts summing to exactly the bar's length and keeps a
band with volume from rounding away.

A column still needs its eighths — it is a few cells tall and buys
resolution there, against empty background where the glyph's leading
doesn't show. A twenty-cell bar doesn't need them, so the horizontal axis
machinery added for it is gone again; what remains of the sharing is
`split_units`, the largest-remainder split both resolutions use.
edwin-zvs added a commit that referenced this pull request Aug 5, 2026
* Detail a hovered token-meter column as bars per model

Hovering a meter column listed its models as one line of comma-separated
figures. A column is a stack, and the questions asked of it — what was
this mostly, how much of it was real work — are about proportion, so the
division was left to be done by eye; past two models the line read as a
run of text with no shape at all.

The detail is now a small panel: the span and the column's total, then
one row per model with its name, a horizontal bar of that model's share,
and its exact figures (cache-served volume marked as the subset it is).
The bars are the column's own paint laid along a row instead of up one —
one hue per model, the cache-served part in the darker tone at the bar's
start, boundaries carried at eighth resolution — so the detail describes
the graph under the pointer rather than a second vocabulary for it.

Rows follow series order, the order the column stacks them and the
legend names them, so a row's position matches its band. Bars scale to
the hovered column's total, and a model that did any work keeps a
visible bar however small its share. A terminal too narrow for a bar
that would still separate a tenth from a fifth falls back to the
previous text detail rather than drawing a stub bar.

The project dashboard's meter had no hover detail at all; it now records
its graph rect and shares this one renderer, since scoping the meter to
a project changes which sessions are counted, not what the graph means.

Column paint gains a horizontal axis (`bar_cells`) rather than a second
implementation: same eighth arithmetic and the same fg-over-bg encoding
for a boundary inside a cell, only the glyph table differs.

* Spell out "cached", and keep the hover bars square

Two fixes to the hover detail.

The cached figure was marked with `↺`, which reads as "refresh" and has
to be learned before the row can be read. It now says the word: `18k ·
9.0k cached`. The box was already sized from its rows, so it just gets
wider.

The bars ended on a partial block glyph, inherited from the column paint.
That cost a square edge: cells a band fills outright are painted as
background, and a foreground block beside them is only drawn where the
font puts ink — a font that draws it short of the line box (#1183)
notches the bar's corner, which reads as damage rather than precision.
Bars now spend whole cells only, every one a background fill, so the
rectangle is clean on any font. Largest-remainder apportionment keeps the
cached and fresh parts summing to exactly the bar's length and keeps a
band with volume from rounding away.

A column still needs its eighths — it is a few cells tall and buys
resolution there, against empty background where the glyph's leading
doesn't show. A twenty-cell bar doesn't need them, so the horizontal axis
machinery added for it is gone again; what remains of the sharing is
`split_units`, the largest-remainder split both resolutions use.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant